/**
 * 验证规则
 */
import { RuleObject } from 'antd/lib/form';

export type Validator = RuleObject['validator'];

/**
 *
 * 生成一个Form.Item的自定义校验器
 */
export function craeteValidator(regex: RegExp, message: string): Validator {
  return async (_, value) => {
    // 不对空值校验
    if (value === '' || value === null || typeof value === 'undefined') {
      return;
    }

    if (regex.test(value)) {
      return;
    }

    throw new Error(message);
  };
}

// 用户名
export const userNameReg = /^[a-zA-Z0-9]{4,16}$/;
export const userNameValidator = craeteValidator(userNameReg, '用户名只能输入4-16位字母,数字');

// 纯空格
export const noSpaceReg = /^[^\s]*$/;
export const noSpaceValidator = craeteValidator(noSpaceReg, '不能输入空格');

// 汉字
export const hanZiReg = /^[\u4e00-\u9fa5]{0,}$/g;
export const hanZiValidator = craeteValidator(hanZiReg, '只能输入汉字');

// 中文姓名
export const chineseNameReg = /^[\u4E00-\u9FA5]+(·[\u4E00-\u9FA5]+)*$/;
export const chineseNameValidator = craeteValidator(chineseNameReg, '输入的姓名格式错误');

// 手机号码
export const mobileReg = /^1\d{10}$/;
export const mobileValidator = craeteValidator(mobileReg, '输入的手机号码格式错误');

// 身份证号码
export const idcardReg =
  /^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/;
export const idcardValidator = craeteValidator(idcardReg, '输入的身份证号码格式错误');

// 邮箱
export const emailReg = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/;
export const emailValidator = craeteValidator(emailReg, '输入的邮箱格式有误');

// url地址
// eslint-disable-next-line no-useless-escape
export const urlReg = /^((https?|ftp|file):\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/;
export const urlValidator = craeteValidator(urlReg, 'URL格式错误');

// 车牌号
export const carIdReg =
  /^(([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z](([0-9]{5}[DF])|([DF]([A-HJ-NP-Z0-9])[0-9]{4})))|([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳使领]))$/;
export const carIdValidator = craeteValidator(carIdReg, '车牌号格式错误');

/** 数值 */
// 正整数
export const numPosReg = /^\d+$/;
export const numPosValidator = craeteValidator(numPosReg, '只能输入正整数');

// 正整数带负数
export const numPosNegReg = /^[-]?\d+$/;
export const numPosNegValidator = craeteValidator(numPosNegReg, '只能输入正整数');

// 带小数的正数(小数非强制)
export const numDigReg = /^\d*(\.\d+)?$/;
export const numDigValidator = craeteValidator(numDigReg, '只能输入正数');

// 带小数的正数带负数(小数非强制)
export const numNegDigReg = /^[-]?\d*(\.\d+)?$/;
export const numNegDigValidator = craeteValidator(numNegDigReg, '只能输入正数');
/** end 数值 */

// 简单密码 6-21字母和数字组成
export const passwordReg = /^\S*(?=\S{6,20})(?=\S*\d)(?=\S*[A-Za-z])(?=\S*[!@#$^&*?])\S*$/;
// export const passwordReg = /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,21}$/;
export const passwordValidator = craeteValidator(
  passwordReg,
  '密码长度为6到20位，且必须包含字母，数字，以及特殊字符，特殊字符为：!@#$^&*?'
);
// export const passwordValidator = craeteValidator(passwordReg, '最少6位，字母和数字组成');

/**
 * 复杂密码校验
 * 8-16位字符
 * 含大小写字母,数字,特殊字符($@$!%*#?&)
 * 不能含有连续3位相同的数字或字母
 * 不能含有3位连续的字母
 * 不能含有3位连续的数字
 * 不能含有3位键盘横向方向连续的字母
 */
export const passwordComplexValidator: Validator = async (rule: unknown, value: unknown) => {
  // 不对空值校验
  if (value === '' || value === null || typeof value === 'undefined') {
    return;
  }

  // 通用规则
  const regex = /(?=.*?[a-z])(?=.*?[A-Z])(?=.*?\d)(?=.*?[$@$!%*#?&])/;
  // 字母连续规则
  const strReg =
    /(a(?=b)|b(?=c)|c(?=d)|d(?=e)|e(?=f)|f(?=g)|g(?=h)|h(?=i)|i(?=j)|j(?=k)|k(?=l)|l(?=m)|m(?=n)|n(?=o)|o(?=p)|p(?=q)|q(?=r)|r(?=s)|s(?=t)|t(?=u)|u(?=v)|v(?=w)|w(?=x)|x(?=y)|y(?=z)|z(?=a)){2}[a-z]/i;
  // 数字连续规则
  const numReg = /(0(?=1)|1(?=2)|2(?=3)|3(?=4)|4(?=5)|5(?=6)|6(?=7)|7(?=8)|8(?=9)|9(?=0)){2}\d/;
  // 键盘字母横向连续规则
  const keyboardHorizontalReg =
    /(q(?=w)|w(?=e)|e(?=r)|r(?=t)|t(?=y)|y(?=u)|u(?=i)|i(?=o)|o(?=p)|p(?=q) |a(?=s)|s(?=d)|d(?=f)|f(?=g)|g(?=h)|h(?=j)|j(?=k)|k(?=l)|l(?=a) | z(?=x)|x(?=c)|c(?=v)|v(?=b)|b(?=n)|n(?=m)|m(?=z)){2}[a-z]/i;
  // 多个相同字母、数字规则
  const sameReg = /(\w)\1{2}/i;

  if (typeof value !== 'string') {
    return;
  }

  if (value.length > 20 || value.length < 8) {
    throw new Error('请输入8-16位字符');
  }

  if (!regex.test(value)) {
    throw new Error('密码必须含大小写字母,数字,特殊字符($@$!%*#?&)');
  }

  if (sameReg.test(value)) {
    throw new Error('密码不能含有连续3位相同的数字或字母');
  }

  if (strReg.test(value)) {
    throw new Error('密码不能含有3位连续的字母');
  }

  if (numReg.test(value)) {
    throw new Error('密码不能含有3位连续的数字');
  }

  if (keyboardHorizontalReg.test(value)) {
    throw new Error('密码不能含有3位键盘横向方向连续的字母');
  }
};
